/**
 * @author Marcelo Miranda Carneiro - mcarneiro@gmail.com
 */
;(function(scope, $, cookie){
	if(!$) return;

	var Control = function(p_id, p_nodes){
		this.holder = p_nodes.table;
		var templateNode = $('.template:first', this.holder).removeClass('template');
		this.idCounter = 0;
		this.template = templateNode.clone(true);
		this.lines = [];
		this.percent = new Percent(p_nodes.percent);
		this.cookies = new Cookies(p_id);
		this.carret = -1;
		
		this._createNewLine = function(p_node) {
			var line = new Line(p_node || this.template.clone(true), this.idCounter++);
			this._applyLineEvents(line);
			if(this.carret+1 >= this.lines.length || this.carret < 0){
				this.lines.push(line);
			}else{
				this.lines.splice(this.carret+1, 0, line);
			}
			return line;
		};
		this._applyLineEvents = function(p_line){
			var _this = this;
			p_line
				.bind('multiline', function(e, data){
					_this._createLinesByText(data.text);
				})
				.bind('removed', function(e, data){
					_this.remove($(this).data('line'));
				})
				.bind('select', function(e, data){
					_this.refresh();
				})
				.bind('current', function(e, data){
					_this.carret = $.inArray(data.instance, _this.lines);
				});
		};
		this._createLinesByText = function(p_texts){
			var _this = this,
				line = null,
				fragment = document.createDocumentFragment();
			$.each(p_texts, function(i, item){
				if(item != "" || (item == "" && i == p_texts.length-1)){
					line = _this._createNewLine();
					line.setText(item);
					fragment.appendChild(line.holder[0]);
				}
			});
			this.lines[this.carret > 0 ? this.carret : 0].holder.after(fragment);
			this.lines[this.carret+1].focus();
			this.refresh();
		};
		this.remove = function(p_line) {
			var _this = this;
			if(this.lines.length == 1){ 
				this.lines[0].holder.one('click', function(){
					_this.trigger('firstClick');
				});
				this.trigger('oneEmptyLine');
				return false;
			}
			var index = $.inArray(p_line, this.lines);
			if(index >= 0){
				this.lines[index].dispose();
				this.lines.splice(index, 1);
			}
			this.refresh();
		};
		this.refresh = function() {
			var total = 0,
				selected = 0;
			$.each(this.lines, function(i, item){
				total += item.totalItems;
				selected += item.selectedItems;
			});
			this.percent.setPercent((selected / total) * 100);
		};
		
		this._getCookieData = function() {
			var _this = this,
				data = this.cookies.getData();
			if(data && data.length > 0){
				_this.trigger('firstClick');
				this._createLinesByText(data);
				this.remove(this.lines[0]);
			}else{
				this.lines[0].holder.one('click', function(){
					_this.trigger('firstClick');
				});
			}
		};
		this._extendEvents = function() {
			var _this = this;
			$.each(['bind', 'unbind', 'trigger'], function(i, name){
				_this[name] = function(){
					return _this.holder[name].apply(_this.holder, Array.prototype.slice.call(arguments));
				};
			});
		};
		this._recordCookies = function() {
			if(this.cookies.id){
				var text = null, texts = [];
				$.each(this.lines, function(i, item) {
					text = item.getText();
					if(text && text.replace(/[\s\n\r]+/g)){
						texts.push(text.replace(/[\n\r]/g, ''));
					}
				});
				this.cookies.setData(texts);
			}
		};
		this._applyUnloadEvent = function() {
			var _this = this;
			$(window).one('unload', function() {
				_this._recordCookies();
			});
		};
		this.clear = function() {
			var _this = this;
			this.cookies.clear();
			$.each(_this.lines, function(i, item) {
				item.dispose();
			});
			this.lines.length = 0;
			this._createNewLine();
			this.holder.append(_this.lines[0].holder);
			this.trigger('oneEmptyLine');
			this.lines[0].holder.one('click', function(){
				_this.trigger('firstClick');
			});
			this.refresh();
		};
		this.createProject = function(p_id) {
			this.cookies.id = p_id;
			this._recordCookies();
		};
		
		this.getContent = function() {
			var text, texts = [];
			$.each(this.lines, function(i, item) {
				if(text = item.getText()){
					texts.push(text);
				}
			});
			return texts.join('\n');
		};
		
		this.constructor = function(){
			this._createNewLine(templateNode);
			this._extendEvents();
			this._applyUnloadEvent();
		};
		this.build = function() {
			this._getCookieData();
			this.refresh();
		};
		this.constructor();
	},
	Line = function(p_holder, p_id){
		this.holder = p_holder;
		this.holder.data('line', this);
		this.field = new TextField($('.desc', this.holder));
		this.id = 'c_'+p_id;
		this.buttons = [];
		this.totalItems = 0;
		this.selectedItems = 0;
		
		var checkBoxesNodes = $('.browser', this.holder);
		
		this.buildCheckboxes = function(){
			var _this = this;
			checkBoxesNodes.each(function(i, elm){
				_this.totalItems++;
				_this.buttons[i] = new Button($(elm));
				_this.buttons[i].holder.bind('button-select', function(e, data){
					_this.selectedItems += (data.checked ? 1 : -1);
					_this.trigger('select', {total: _this.totalItems, selected: _this.selectedItems});
				});
			});
		};
		this.setId = function(p_id){
			if(!p_id){ return false; }
			this.id = p_id;
			$.each(this.buttons, function(i, item){
				item.setId(p_id+'_'+i);
			});
			this.field.setId(p_id+'_desc');
		};
		this.focus = function() {
			this.field.focus();
		};
		this.setText = function(p_text){
			this.field.setText(p_text);
		};
		this.getText = function(){
			return this.field.getText();
		};
		this.dispose = function() {
			this.field.dispose();
			$.each(this.buttons, function() {
				this.dispose();
			});
			this.holder.remove();
		};
		
		this.constructor = function(){
			var _this = this;
			this.buildCheckboxes();
			this.setId(this.id);
			this.field
				.bind('removed', function(){
					_this.trigger('removed');
				});
			this.field.textarea.bind('focus', function(e, data){
				_this.trigger('current', {instance: _this});
			});
			$.each(['bind', 'unbind', 'trigger'], function(i, name){
				_this[name] = function(){
					return _this.holder[name].apply(_this.holder, Array.prototype.slice.call(arguments));
				};
			});
		};
		this.constructor();
	},
	TextField = function(p_holder){
		this.holder = p_holder;
		this.holder.data('textfield', this);
		this.textareaHolder = $(document.createElement('div'));
		this.textarea = $(document.createElement('textarea')).addClass('fldDescription');
		this.flags = {
			'added': false
		};
		this.textareaHolder.append(this.textarea);
		
		this.addTextArea = function(){
			if(this.textareaHolder[0].parentNode != this.holder[0]){
				this.flags.added = true;
				this.holder
					.text('')
					.append(this.textareaHolder);
			}
		};
		this.removeTextArea = function(){
			if(this.textarea[0].value.length === 0 && this.flags.added){
				this.flags.added = false;
				this.textareaHolder[0].parentNode.removeChild(this.textareaHolder[0]);
				this.holder.trigger('removed');
			}
		};
		this.verifyText = function(){
			var enters = this.textarea[0].value.split('\n');
			if(enters.length > 1){
				this.holder.trigger('multiline', {text: enters.slice(1)});
				this.textarea[0].value = enters[0].replace(/[\n\r]+/g, '');
			}else{
				this.removeTextArea();
			}
			this.refresh();
		};
		this.setId = function(p_id){
			this.textarea[0].id = p_id;
		};
		this.focus = function() {
			this.textarea[0].focus();
		};
		this.setText = function(p_text){
			this.addTextArea();
			this.textarea[0].value = p_text;
			var _this = this;
			setTimeout(function(){
				_this.refresh();
			}, 100);
		};
		this.getText = function() {
			return this.textarea[0].value;
		};
		this.refresh = function() {
			if(this.textarea[0].scrollHeight != this.textarea[0].offsetHeight){
				this.textarea.css('height', this.textarea[0].scrollHeight);
			}
		};
		this.dispose = function() {
			this.textarea.remove();
			this.holder.remove();
		};
		
		this.constructor = function() {
			var _this = this;
			this.holder.click(function(e){
				_this.addTextArea();
				_this.textarea[0].focus();
			});
			this.textarea.bind('keyup', function(e){
				_this.verifyText();
			});
			this.textarea.bind('blur', function(e){
				_this.removeTextArea();
				_this.trigger('blurred');
			});
			
			$.each(['bind', 'unbind', 'trigger'], function(i, name){
				_this[name] = function(){
					return _this.holder[name].apply(_this.holder, Array.prototype.slice.call(arguments));
				};
			});
		};
		this.constructor();
	},
	Button = function(p_holder){
		this.holder = p_holder;
		this.holder.data('button', this);
		this.label = $('label:first', this.holder);
		this.input = $('input:first', this.holder).attr('checked', false);
		this.selected = false;
		
		this.setId = function(p_id){
			this.label.attr('for', p_id);
			this.input[0].id = p_id;
		};
		this.dispose = function() {
			this.holder.remove();
			this.input.remove();
			this.label.remove();
		};
		
		this.constructor = function(){
			var _this = this;
			this.input.click(function(e){
				_this.selected = !_this.selected;
				_this.label[(_this.selected ? 'add' : 'remove') + 'Class']('checked');
				_this.holder.trigger('button-select', {checked: _this.selected});
			});
			_disableSelection(this.holder);

			$.each(['bind', 'unbind', 'trigger'], function(i, name){
				_this[name] = function(){
					return _this.holder[name].apply(_this.holder, Array.prototype.slice.call(arguments));
				};
			});
		};
		this.constructor();
	},
	Percent = function(p_holder) {
		this.holder = p_holder;
		this.bar = $('.percent:first', this.holder);
		this.label = $('.percent-label:first', this.holder);
		
		this.setPercent = function(p_value) {
			this.bar.stop().animate({
				width: p_value+'%'
			}, 300, 'swing');
			this.label.text(Math.floor(p_value)+'%');
			switch(true){
				case (Math.max(p_value, 30) === 30):
					this.bar
						.addClass('low')
						.removeClass('medium high');
					break;
				case (Math.max(p_value, 50) === 50):
					this.bar
						.addClass('medium')
						.removeClass('low high');
					break;
				case (p_value === 100):
					this.bar
						.addClass('high')
						.removeClass('low medium');
					break;
			}
		};
	},
	Cookies = function(p_id) {
		this.id = p_id;
		this.data = [];

		this.getData = function() {
			if(this.data.length === 0 && this.id){
				this.data = cookie(this.id) ? cookie(this.id).split('||') : [];
			}
			return this.data;
		};
		this.clear = function() {
			if(this.id){
				cookie(this.id, null);
			}
		};
		this.setData = function(p_data) {
			if(!this.id) return;
			if(p_data){ this.data = p_data; }
			this.clear();
			cookie(this.id, this.data.join('||'), {expires: 90});
		};
	},
	ProjectCreator = function(p_holder) {
		this.holder = p_holder;
		this.parent = p_holder.parent();
		this.textfield = $(document.createElement('input'))
			.addClass('fldProject')
			.attr('type', 'text')
			.attr('name', 'projectName')
			.hide();
		
		this._extendEvents = function() {
			var _this = this;
			$.each(['bind', 'unbind', 'trigger'], function(i, name){
				_this[name] = function(){
					return _this.holder[name].apply(_this.holder, Array.prototype.slice.call(arguments));
				};
			});
		};
		this.constructor = function() {
			var _this = this;
			this._extendEvents();
			
			this.parent.append(this.textfield);
			this.textfield.keyup(function(e) {
				switch(e.keyCode){
					case 13: // enter
						_this.holder.show();
						_this.textfield.hide();
						if(_this.textfield[0].value){
							_this.trigger('onCreate', {id: _this.textfield[0].value});
						}
						break;
					case 27: // esc
						_this.holder.show();
						_this.textfield.hide();
						break;
				}
			});
			this.holder.click(function(e) {
				_this.holder.hide();
				_this.textfield.css('display', 'inline');
				_this.textfield[0].focus();
				return false;
			});
			
		};
		this.constructor();
	},
	
	
	_enableSelection = function(p_node) {
		if(p_node){
			p_node.attr('unselectable', 'off')
				.css('MozUserSelect', '')
				.unbind('selectstart.ui');
		}
	},
	_disableSelection = function(p_node) {
		if(p_node){
			_unhighlightText();
			p_node.attr('unselectable', 'on')
				.css('MozUserSelect', 'none')
				.bind('selectstart.ui', function() { return false; });
		}
	},
	_unhighlightText = function(){
		switch(true){
			case !!(window.getSelection):
				window.getSelection().removeAllRanges();
				break;
			case !!(document.selection):
				document.selection.clear();
				document.selection.empty();
				break;
		}
	};
	
	// public classes
	scope.Control = Control;
	scope.ProjectCreator = ProjectCreator;

})(window, jQuery, jQuery.cookie);